package com.yubest.security.filter;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yubest.security.bean.Response;
import com.yubest.security.bean.UserInfo;
import com.yubest.security.consts.Consts;
import com.yubest.security.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

@Slf4j
public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    public LoginFilter(AuthenticationManager authenticationManager) {
        setAuthenticationManager(authenticationManager);
        setFilterProcessesUrl("/login");
    }

    /**
     * 登陆，密码校验
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        UsernamePasswordAuthenticationToken authRequest;
        try (InputStream is = request.getInputStream()) {
            JSONObject node = JSONUtil.parseObj(is);
            String username = node.getStr("username");
            String password = node.getStr("password");
            authRequest = new UsernamePasswordAuthenticationToken(username, password);
        } catch (IOException e) {
            log.error("登陆参数获取失败", e);
            authRequest = new UsernamePasswordAuthenticationToken("", "");
        }
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * 登陆成功时，执行
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        UserInfo userInfo = (UserInfo) authResult.getPrincipal();
        log.info("登陆成功，username：{}", authResult.getName());
        TokenService tokenService = SpringUtil.getBean(TokenService.class);
        String token = tokenService.create(userInfo);
        Response<String> data = Response.ok(token);
        ServletUtil.write(response, JSONUtil.toJsonStr(data), "application/json;charset=utf-8");
    }

    /**
     * 登陆失败时，执行
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        log.error("登陆失败");
        Response<String> data = Response.error(Consts.NOT_LOGIN_CODE, "登陆失败");
        ServletUtil.write(response, JSONUtil.toJsonStr(data), "application/json;charset=utf-8");
    }
}
